package modules.pathloss;

import com.vividsolutions.jts.geom.Geometry;

import javax.naming.directory.InvalidAttributesException;

import datatypes.Antenna;
import modules.pathloss.model.CostHata;
import modules.pathloss.model.Erceg;
import modules.pathloss.model.FreeSpace;
import modules.pathloss.model.WI_LOS;
import tools.settings.Settings;
import tools.settings.SettingsMissingException;

/**
 * <p>The MAPL implementation for omnidirectional antennas. </p>
 *
 * @author Lynne Vandousselaere
 */
class OdMAPL implements MAPL {
    // the linkbudget calculator

    LinkBudgetCalculator linkbudget = new LinkBudgetCalculator();

    // the pathloss adapter for calculating pathloss stuff
    PathLossAdapter pathloss = PathLossAdapter.getInstance();
    private final int sides = 32;
    private String[] nsettings = {"plm"};

    /**
     * <p>Constructs a new MAPL for omnidirectional antennas.</p>
     */
    public OdMAPL() {
    }

    @Override
    public Geometry getCoverage(Antenna a, Settings settings)
            throws SettingsMissingException {
        double radius = getRadius(a, settings, 1);

        return tools.gis.GisTools.createCircleInLambertFormat(a.getX(), a.getY(), radius, sides);
    }

    @Override
    public double getRangeRadius(Antenna a, Settings settings)
            throws SettingsMissingException {
        String[] snames = {"rangeFactor"};
        if (!settings.contains(snames))
            throw SettingsMissingException.generate("OdMAPL", "getRangeRadius", snames);

        int rangeFactor = Integer.parseInt(settings.getSettingsValue("rangeFactor"));
        return getRadius(a, settings, rangeFactor);
    }

    /** **********************************************
     *  Private methods
     *  **********************************************/
    /**
     * <p>Calculates the radius of an antenna where there is maximum allowable 
     * path loss from the given antenna, settings and rangefactor.</p>
     *
     * @param a
     * @param settings
     * @param rangefactor
     * @return
     * @throws javax.naming.directory.InvalidAttributesException
     */
    private double getRadius(Antenna a, Settings settings, int rangefactor)
            throws SettingsMissingException {
        double downlink = linkbudget.getPathLossComponent(settings, a, true);
        double uplink = linkbudget.getPathLossComponent(settings, a, false);
        double[] pl_log_d = getLogDistance(a, settings);

        // convert back. log10 distance (m) = (linkbudget - a)/b *1000
        // or distance (m) = 10^((lb-a)/b) *1000
        double radius_dl = Math.pow(10, (downlink - pl_log_d[0]) / pl_log_d[1]) * 1000;
        double radius_ul = Math.pow(10, (uplink - pl_log_d[0]) / pl_log_d[1]) * 1000;

        return (Math.min(radius_dl, radius_ul) * rangefactor);
    }

    private double[] getLogDistance(Antenna a, Settings settings)
            throws SettingsMissingException {
        String plm_par = settings.getSettingsValue("PLM");

        if (plm_par == null)
            throw SettingsMissingException.generate("OdMAPL", "getLogDistance", nsettings);
        else {
            if (plm_par.equalsIgnoreCase("costhata"))
                return new CostHata().getLogDistance(settings, a);
            if (plm_par.equalsIgnoreCase("freespace"))
                return new FreeSpace().getLogDistance(settings, a);
            if (plm_par.equalsIgnoreCase("wilos"))
                return new WI_LOS().getLogDistance(settings, a);
            if (plm_par.equalsIgnoreCase("erceg"))
                return new Erceg().getLogDistance(settings, a);
        }

        // faulty name of plm.
        throw new IllegalArgumentException("OdMAPL - (getLogDistance) " +
                "argument PLM is incorrect (" + plm_par + "), allowed are: COSTHATA, FREESPACE, WILOS");
    }
}
